<template>
	<scroll-view
		class="load-list"
		:scroll-y="true"
		:enhanced="true"
		:refresherEnabled="refresherEnabled"
		:refresherTriggered="refreshData.refreshed"
		refresherBackground="#F6F7F8"
		@refresherrefresh="handleRefresherRefresh"
		@scrolltolower="handleScrollToLower"
		:style="{ height: scrollHeight ? `${scrollHeight}px` : '100%' }"
	>
		<view class="load-list__box" :style="customStyle">
			<view v-for="(item, index) in list" :key="item[idKey]" :style="itemCustomStyle">
				<slot :dataItem="{ ...item, $index: index }" />
			</view>

			<view class="load-list__finished-text" v-if="finished && list.length">
				{{ finishedText }}
			</view>
      <nut-empty image="empty" description="暂无数据" v-if="loaded && list.length === 0"></nut-empty>
			<!-- <slot name="empty" v-if="loaded && list.length === 0" /> -->
		</view>
	</scroll-view>
</template>

<script setup>
import { computed, onBeforeMount, reactive, ref, unref, watch } from 'vue';
import { isNil, debounce } from 'lodash-es';

const emit = defineEmits(['currentData', 'after-reload']);

const defaultAdapter = (result, pageSize) => {
	const _data = result.data;

	if (props.withoutTotal) {
		return {
			listData: _data?.records || _data,
			listTotal: _data?.total || undefined
		};
	}

	if (isNil(_data)) {
		return {
			listData: [],
			listTotal: 0
		};
	}

	if (!isNil(_data.total)) {
		return {
			listData: _data.records || [],
			listTotal: _data.total
		};
	}

	return {
		listData: _data.results || [],
		listTotal: ((_data.totalPage || 1) - 1) * pageSize + (_data.results?.length || 0)
	};
};

const props = defineProps({
	requestFn: { type: Function, required: true },
	requestParams: { type: Object, default: {} },
	responseAdapter: { type: Function },
	immediate: { type: Boolean, default: true },
	finishedText: { type: String, default: '' },
	noDataText: { type: String, default: '暂无数据' },
	idKey: { type: String, default: 'id' },
	refresherEnabled: { type: Boolean, default: true }, // 下拉刷新
	scrollHeight: { type: Number }, //高度
	listContainerClass: { type: String, default: '' },
	withoutTotal: { type: Boolean, default: false }, // 是否使用total
	customStyle: { type: String, default: '' },
	itemCustomStyle: { type: String, default: '' },
	loadImmediate: { type: Boolean, default: true }
});

const list = ref([]);
const loading = ref(false);
const loaded = ref(false);
const currentPageData = ref([]);

const paginationData = reactive({
	total: 0,
	currentPage: 1,
	pageSize: 10
});

const refreshData = reactive({
	refreshed: false
});

const finished = computed(() => {
	return (
		unref(loaded) &&
		((!props.withoutTotal && unref(list).length >= paginationData.total) ||
			(props.withoutTotal && currentPageData.value.length < paginationData.pageSize))
	);
});

const load = () => {
	const params = {
		...props.requestParams,
		pageNo: paginationData.currentPage,
		pageSize: paginationData.pageSize
	};

	return props.requestFn(params).then(result => {
		const { listData, listTotal } = defaultAdapter(result, paginationData.pageSize);

		currentPageData.value = listData;

		if (refreshData.refreshed) {
			list.value = [];
		}

		list.value = [...list.value, ...listData];
		paginationData.total = listTotal || list.value.length;

		if (paginationData.total > list.value.length || (props.withoutTotal && listData?.length == paginationData.pageSize)) {
			paginationData.currentPage++;
		}

		// emit('currentData', { ...paginationData, list: list.value });
	});
};

const execLoad = () => {
	if (props.requestParams === null) {
		return;
	}

	if (unref(finished) || unref(loading)) {
		return;
	}

	loading.value = true;
	// uni.showLoading({ title: '加载中' });

	return load()
		.then(() => {
			loaded.value = true;
		})
		.finally(() => {
			loading.value = false;
			// uni.hideLoading();
		});
};

const reload = () => {
	loaded.value = false;
	paginationData.currentPage = 1;
	paginationData.total = 0;

	if (!refreshData.refreshed) {
		list.value = [];
	}

	return execLoad();
};

const handleScrollToLower = () => {
	execLoad();
};

const handleRefresherRefresh = () => {
	refreshData.refreshed = true;

	reload().then(() => {
		refreshData.refreshed = false;
		emit('after-reload')
	});
};

watch(
	() => props.requestParams,
	debounce(() => {
		reload();
	}, 400),
	{ deep: true }
);

onBeforeMount(() => {
	props.loadImmediate && execLoad();
});

defineExpose({
	reload
});
</script>

<style lang="scss">
$b: load-list;

.#{$b} {
	height: 100%;
	width: 100%;

	&__finished-text {
		width: 100%;
		line-height: 20px;
		font-size: 14px;
		text-align: center;
		color: #86909c;
	}

	&__box {
		width: 100%;
	}
}
</style>
